package cn.congine.wizarpos.mall.service.impl;

import java.io.IOException;
import java.net.HttpURLConnection;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;

import cn.congine.wizarpos.mall.model.open.AccessTokenInput;
import cn.congine.wizarpos.mall.model.open.AccessTokenOutput;
import cn.congine.wizarpos.mall.model.open.MerchantDef;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryInput;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryOutput;
import cn.congine.wizarpos.mall.model.open.AccessTokenOutput.Result;
import cn.congine.wizarpos.mall.utils.SysConstants;

import com.alibaba.fastjson.JSONObject;

@Service("wxHttpClient")
public class WxHttpClient {
	private static final String WX_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?grant_type=authorization_code";
	private static final String WX_SHAKE_URL = "https://api.weixin.qq.com/shakearound/user/getshakeinfo?access_token=";
	private static final int DEFAULT_TIMEOUT = 10000;
	private static final String WPCharset = "UTF-8";
	private static final String JsonContentType = "application/json";
	private static final String XmlContentType = "application/xml";
//	private CloseableHttpClient httpClient;

	@Resource(name = "messageSource")
	private MessageSource messageSource;

	@Autowired
	private WizarposOpenRestClient wizarposOpenRestClient;

	public String post(String url, String data) {
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(DEFAULT_TIMEOUT)
				.setConnectTimeout(DEFAULT_TIMEOUT)
				.setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY).build();
		CloseableHttpClient httpClient = HttpClients.custom()
				.setDefaultRequestConfig(requestConfig).build();
		
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			StringEntity postEntity = new StringEntity(data,
					ContentType.create(JsonContentType, WPCharset));
			httpPost.setEntity(postEntity);
			response = httpClient.execute(httpPost);
			if (response.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
				throw new Exception("Access failed");
			}
			byte[] result = EntityUtils.toByteArray(response.getEntity());
			return new String(result, WPCharset);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
				}
			}
		}
		return "";
	}

	public String postXML(String url, String data) {
		
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(DEFAULT_TIMEOUT)
				.setConnectTimeout(DEFAULT_TIMEOUT)
				.setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY).build();
		CloseableHttpClient httpClient = HttpClients.custom()
				.setDefaultRequestConfig(requestConfig).build();	
		
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			StringEntity postEntity = new StringEntity(data,
					ContentType.create(XmlContentType, WPCharset));
			httpPost.setEntity(postEntity);
			response = httpClient.execute(httpPost);
			if (response.getStatusLine().getStatusCode() != HttpURLConnection.HTTP_OK) {
				throw new Exception("Access failed");
			}
			byte[] result = EntityUtils.toByteArray(response.getEntity());
			return new String(result, WPCharset);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
				}
			}
		}
		return "";
	}

	public String sendMessage(String url, String data) {
		
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(DEFAULT_TIMEOUT)
				.setConnectTimeout(DEFAULT_TIMEOUT)
				.setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY).build();
		CloseableHttpClient httpClient = HttpClients.custom()
				.setDefaultRequestConfig(requestConfig).build();
		
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		try {
			StringEntity postEntity = new StringEntity(data,
					ContentType.create(JsonContentType, WPCharset));
			httpPost.setEntity(postEntity);
			response = httpClient.execute(httpPost);

			return EntityUtils.toString(response.getEntity());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
				}
			}
		}
		return "";
	}

	public String getOpenId(String code, String state) throws Exception {
		// 商户数据
		MerchantDefQueryInput input = new MerchantDefQueryInput();
		input.setMid(state);
		MerchantDefQueryOutput output = (MerchantDefQueryOutput) wizarposOpenRestClient.post(input, "/merchantdef/info", MerchantDefQueryOutput.class);		
		if (output == null || !SysConstants.OPEN_SUCCESS.equals(output.getCode()) 
				|| StringUtils.isEmpty(output.getResult().getWeixinAppId())
				|| StringUtils.isEmpty(output.getResult().getWeixinAppSecret())) {
			throw new Exception("merchant missing:" + state);
		} 
		MerchantDef sysMerchantDef = output.getResult();
		
		String appId = sysMerchantDef.getWeixinAppId();
		if (StringUtils.isEmpty(appId)) {
			throw new Exception("merchant appID missing:" + state);
		}
		
		String appsecret = sysMerchantDef.getWeixinAppSecret();
		if (StringUtils.isEmpty(appsecret)) {
			throw new Exception("merchant appSecert missing:" + state);
		}
		
		String url = WX_URL + "&appid=" + appId + "&secret=" + appsecret
				+ "&code=" + code;

		String openid = null;
		for (int i = 0; i < 5; i++) { // 考虑网络问题，最多请求5次
			String response = post(url, "");
			JSONObject json = JSONObject.parseObject(response);
			
			if (json != null && json.containsKey("openid")) {
				openid = json.getString("openid");
				break;
			} else {
				System.out.println("---------getOpenId------error-----");
				System.out.println(json);
			}
		}

		return openid;
	}
	
	public String getShakeOpenId(String ticket, String mid) throws Exception {
		AccessTokenInput jsInput = new AccessTokenInput();
		jsInput.setMid(mid);
		AccessTokenOutput jsOutput = (AccessTokenOutput) wizarposOpenRestClient.post(jsInput, "/weixin/accesstoken", AccessTokenOutput.class);		
		String assessToken = null;
		if (jsOutput == null || SysConstants.OPEN_ERROR.equals(jsOutput.getCode())) {
			throw new Exception("system error");
		} else if (SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
			throw new Exception("merchant missing:" + mid);
		} else {
			Result apiTicket = jsOutput.getResult();
			if (apiTicket == null) {
				throw new Exception("system error");
			}
			assessToken = apiTicket.getToken();
		}
		
		String url = WX_SHAKE_URL + assessToken;
		JSONObject param = new JSONObject();
		param.put("ticket", ticket);
		
		String openid = null;
		for (int i = 0; i < 5; i++) { // 考虑网络问题，最多请求5次
			String response = post(url, param.toString());
			JSONObject json = JSONObject.parseObject(response);
			
			if (json != null && json.containsKey("errcodde") && json.getIntValue("errcodde") == 0) {
				openid = json.getJSONObject("data").getString("openid");
				break;
			} else {
				System.out.println("---------getShakeOpenId error: ticket = " + ticket);
				System.out.println(json);
			}
		}

		return openid;
	}

}